/*
 *  Writer.cpp
 *  Compiler
 *
 *  Created by Jacopo De Stefani on 3/5/12.
 *  Copyright 2012 Politecnico di Milano. All rights reserved.
 *
 */


#include "Writer.h"

using namespace std;

Writer* Writer::getInstance(){
	if (uniqueInstance != NULL) {
		uniqueInstance = new Writer;
		uniqueInstance->initWriter();
	}
	return uniqueInstance;
}

void Writer::initWriter(){
	gpCodeFile.open("a.out", ios::out);
	if (!gpCodeFile) {
		cerr << "Error in creating the output file. Terminating the application";
		exit(1);
	}
}

//PUSH OPERATIONS
//Writes code corresponding to the move of a int value from sourceAddr on top of the stack.
void Writer::movIntTop(int sourceAddr){
	gpCodeFile << "ldo i " << sourceAddr << endl;
}

//Writes code corresponding to the move of a bool value from sourceAddr on top of the stack.
void Writer::movBoolTop(int sourceAddr){
	gpCodeFile << "ldo b " << sourceAddr << endl;
}

//Writes code corresponding to the push of a constant int value on top of the stack.
void Writer::putIntTop(int intValue){
	gpCodeFile << "ldc i " << intValue << endl;
}

//Writes code corresponding to the push of a constant bool value on top of the stack.
void Writer::putBoolTop(bool boolValue){
	gpCodeFile << "ldc b " << boolValue << endl;
}

//Writes code corresponding to the duplication of the int value on top of the stack.
void Writer::dupIntTop(){
	gpCodeFile << "dup i" << endl;
}
//Writes code corresponding to the duplication of the bool value on top of the stack.
void Writer::dupBoolTop(){
	gpCodeFile << "dup b" << endl;
}

//POP OPERATIONS
//Writes code corresponding to the store of the int value on top of the stack at destAddr location.
void Writer::storeIntAt(int destAddr){
	gpCodeFile << "sro i " << destAddr << endl;
}

//Writes code corresponding to the store of the bool value on top of the stack at destAddr location.
void Writer::storeBoolAt(int destAddr){
	gpCodeFile << "sro b " << destAddr << endl;
}

//Writes code corresponding to the pop of the value on top of the stack.
void Writer::popTop(){
	gpCodeFile << "pop" << endl;
}

//ARITHMETIC OPERATIONS
//Writes code corresponding to the add of the integer values occuping the two topmost locations on the stack.
void Writer::addTop2(){
	gpCodeFile << "add i" << endl;
}
//Writes code corresponding to the subtraction of the integer values occuping the two topmost locations on the stack.
void Writer::subTop2(){
	gpCodeFile << "sub i" << endl;
}
//Writes code corresponding to the multiplication of the integer values occuping the two topmost locations on the stack.
void Writer::mulTop2(){
	gpCodeFile << "mul i" << endl;
}
//Writes code corresponding to the division of the integer values occuping the two topmost locations on the stack.
void Writer::divTop2(){
	gpCodeFile << "div i" << endl;
}
//Writes code corresponding to the negation of the value on top of the stack.
void Writer::negTop(){
	gpCodeFile << "neg i" << endl;
}
	
//BOOLEAN OPERATIONS
//Writes code corresponding to the logical and of the bool values occuping the two topmost locations on the stack.
void Writer::andTop2(){
	gpCodeFile << "and b" << endl;
}
//Writes code corresponding to the logical or of the bool values occuping the two topmost locations on the stack.
void Writer::orTop2(){
	gpCodeFile << "or b" << endl;
}
//Writes code corresponding to the logical not of the value on top of the stack.
void Writer::notTop(){
	gpCodeFile << "not b" << endl;
}
	
//COMPARISON OPERATIONS
//Writes code corresponding to the "greater or equal than" comparison of the int values occuping the two topmost locations on the stack.
void Writer::geqTop2(){
	gpCodeFile << "geq i" << endl;
}
//Writes code corresponding to the "less or equal than" comparison of the int values occuping the two topmost locations on the stack.
void Writer::leqTop2(){
	gpCodeFile << "leq i" << endl;
}
//Writes code corresponding to the "greater than" comparison of the int values occuping the two topmost locations on the stack.
void Writer::grtTop2(){
	gpCodeFile << "grt i" << endl;
}
//Writes code corresponding to the "less than" comparison of the int values occuping the two topmost locations on the stack.
void Writer::lesTop2(){
	gpCodeFile << "les i" << endl;
}
//Writes code corresponding to the "equal to" comparison of the int values occuping the two topmost locations on the stack.
void Writer::equTop2(){
	gpCodeFile << "equ i" << endl;
}
//Writes code corresponding to the "not equal to" comparison of the int values occuping the two topmost locations on the stack.
void Writer::neqTop2(){
	gpCodeFile << "neq i" << endl;
}
	
//I/O OPERATIONS
//Writes code corresponding to the write I/O operation of the value on top of the stack.
void Writer::printTop(){
	gpCodeFile << "prin" << endl;
}
//Writes code corresponding to the read I/O operation whose result is put on top of the stack.
void Writer::readToTop(){
	gpCodeFile << "read" << endl;
}
	
//JUMP OPERATIONS
//Writes code corresponding to the definition of a label to allow jumps.
void Writer::defLabel(string label){
	gpCodeFile << "define " << label << endl;
}

//Writes code corresponding to the unconditional jump to label.
void Writer::uncondJumpTo(string label){
	gpCodeFile << "ujp " << label << endl;
}
//Writes code corresponding to the conditional jump to label only if the value on top of the stack is false.
void Writer::condFalseJumpTo(string label){
	gpCodeFile << "fjp " << label << endl;
}
	
//SUBROUTINE OPERATIONS
//Writes code corresponding to the allocation of a new stack frame, given the current nesting (0 : Main function, 1 : Subroutine).
void Writer::allocSF(int currNest){
	gpCodeFile << "mst " << currNest << endl;
}
//Writes code corresponding to the function call of funcName with parNum parameters.
void Writer::callFunc(int parNum,string funcName){
	gpCodeFile << "cup " << parNum << " " << funcName << endl;
}
//Writes code corresponding to the return instruction of a function.
void Writer::retFunc(){
	gpCodeFile << "retf" << endl;
}
//Writes code corresponding to the return instruction of a procedure.
void Writer::retProc(){
	gpCodeFile << "retp" << endl;
}

	
//SUBROUTINE PUSH OPERATIONS
//Writes code corresponding to the move of a int value from sourceAddr on top of the current stack frame.
void Writer::movIntTopFunc(int sourceAddr){
	gpCodeFile << "lod i 0 " << sourceAddr << endl;
}

//Writes code corresponding to the move of a bool value from sourceAddr on top of the current stack frame.
void Writer::movBoolTopFunc(int sourceAddr){
	gpCodeFile << "lod b 0 " << sourceAddr << endl;
}
//Writes code corresponding to the move of a int value from sourceAddr on top of the global stack frame.
void Writer::movIntTopGlob(int sourceAddr){
	gpCodeFile << "lod i 1 " << sourceAddr << endl;
}
//Writes code corresponding to the move of a bool value from sourceAddr on top of the global stack frame.
void Writer::movBoolTopGlob(int sourceAddr){
	gpCodeFile << "lod b 1 " << sourceAddr << endl;
}
	
//SUBROUTINE POP OPERATIONS
//Writes code corresponding to the store of the int value on top of the stack at destAddr relative address with respect to current stack frame.
void Writer::storeIntFunc(int destAddr){
	gpCodeFile << "str i 0 " << destAddr << endl;
}
//Writes code corresponding to the store of the bool value on top of the stack at destAddr relative address with respect to current stack frame.
void Writer::storeBoolFunc(int destAddr){
	gpCodeFile << "str b 0 " << destAddr << endl;
}
//Writes code corresponding to the store of the int value on top of the stack at destAddr absolute address. 
void Writer::storeIntGlob(int destAddr){
	gpCodeFile << "str i 1 " << destAddr << endl;
}
//Writes code corresponding to the store of the bool value on top of the stack at destAddr absolute address.
void Writer::storeBoolGlob(int destAddr){
	gpCodeFile << "str b 1 " << destAddr << endl;
}
//Writes code corresponding to the end of the program.
void Writer::endProg(){
	gpCodeFile << "stp" << endl;
}
	